import random from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) from django_countries.fields import CountryField # from otree.db.models import ForeignKey # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # from slider_task.models import BaseSlider, SliderPlayer # Uncomment for Slider Task (https://github.com/chkgk/slider_task) author = 'Julian Hackinger' doc = """ P2_Real_Effort_Task This is a task that requires real effort from participants. Subjects are shown two images of incomprehensible text. Subjects are required to transcribe (copy) the text into a text entry field. The quality of a subject's transcription is measured by the Levenshtein distance. """ def levenshtein(a, b): """Calculates the Levenshtein distance between a and b.""" n, m = len(a), len(b) if n > m: # Make sure n <= m, to use O(min(n,m)) space a, b = b, a n, m = m, n current = range(n + 1) for i in range(1, m + 1): previous, current = current, [i] + [0] * n for j in range(1, n + 1): add, delete = previous[j] + 1, current[j - 1] + 1 change = previous[j - 1] if a[j - 1] != b[i - 1]: change = change + 1 current[j] = min(add, delete, change) return current[n] def distance_and_ok(transcribed_text, reference_text, max_error_rate): error_threshold = len(reference_text) * max_error_rate distance = levenshtein(transcribed_text, reference_text) ok = distance <= error_threshold return distance, ok class Constants(BaseConstants): name_in_url = 'house_money_effect' players_per_group = 2 num_rounds = 2 # Slider Task num_sliders = 2 # Number of sliders slider_list_high = [] for i in range(1, num_sliders + 1): slider_list_high.append('slider_high' + str(i)) print(slider_list_high) slider_list_low = [] for i in range(1, num_sliders + 1): slider_list_low.append('slider_low' + str(i)) print(slider_list_low) #slider_columns = 3 # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # Initial amount allocated to the player endowment = c(100) multiplier = 2 reference_texts = [ "Revealed preference", "Hex ton satoha egavecen. Loh ta receso minenes da linoyiy xese coreliet ocotine! Senuh asud tu bubo tixorut sola, bo ipacape le rorisin lesiku etutale saseriec niyacin ponim na. Ri arariye senayi esoced behin? Tefid oveve duk mosar rototo buc: Leseri binin nolelar sise etolegus ibosa farare. Desac eno titeda res vab no mes!", ] allowed_error_rates = [0, 0.03] class Subsession(BaseSubsession): pass # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # def creating_session(self): # for p in self.get_players(): # p.prepare_sliders(num=20, min=0, max=4) class Group(BaseGroup): # Dictator game donation = models.CurrencyField( doc="""Amount dictator decided to give""", min=0, max=Constants.endowment, ) # Public goods game total_contribution = models.CurrencyField() individual_share = models.CurrencyField() def set_payoffs_public_goods_game(self): self.total_contribution = sum([p.contribution for p in self.get_players()]) self.individual_share = self.total_contribution * Constants.multiplier / Constants.players_per_group for p in self.get_players(): p.payoff_public_goods_game = (Constants.endowment - p.contribution) + self.individual_share def set_payoffs_beliefs(self): for p in self.get_players(): p.payoff_belief = max(100 - (p.belief - p.get_partner().contribution)**2,0) # class Player(SliderPlayer): # Uncomment for Slider Task (https://github.com/chkgk/slider_task) class Player(BasePlayer): # Roles def role(self): if self.id_in_group == 1: return 'dictator' else: return 'receiver' def get_partner(self): return self.get_others_in_group()[0] # Slider Task def random_min(): return random.randint(0, 40) def random_max(): return random.randint(60, 100) # Slider High Effort def random_initial_high(): return random.randint(*random.choice([(0, 40), (60, 100)])) # Insert_Sliders_High_Start slider_high1 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_high()) slider_high2 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_high()) # Insert_Sliders_High_End # Slider Low Effort def random_initial_low(): return random.randint(*random.choice([(50, 50), (50, 50), (0, 40), (60, 100)])) # Insert_Sliders_Low_Start slider_low1 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_low()) slider_low2 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_low()) # Insert_Sliders_Low_End # Transcribe Task transcribed_text = models.LongStringField() levenshtein_distance = models.IntegerField() # Dictator Game payoff_dictator_game = models.CurrencyField() def set_payoffs_dictator_game(self): self.group.get_player_by_role('dictator').payoff_dictator_game = Constants.endowment - self.group.donation self.group.get_player_by_role('receiver').payoff_dictator_game = self.group.donation # Public Goods Game contribution = models.CurrencyField( min=0, max=Constants.endowment, doc="""The amount contributed by the player""", ) payoff_public_goods_game = models.CurrencyField() # Beliefs belief = models.IntegerField( label=''' "What do you think the other player will contribute?" ''' ) payoff_belief = models.CurrencyField() # CRT crt_bat = models.IntegerField( label=''' A bat and a ball cost 22 dollars in total. The bat costs 20 dollars more than the ball. How many dollars does the ball cost?''' ) crt_widget = models.IntegerField( label=''' "If it takes 5 machines 5 minutes to make 5 widgets, how many minutes would it take 100 machines to make 100 widgets?" ''' ) crt_lake = models.IntegerField( label=''' In a lake, there is a patch of lily pads. Every day, the patch doubles in size. If it takes 48 days for the patch to cover the entire lake, how many days would it take for the patch to cover half of the lake? ''' ) crt_familiarity = models.StringField( choices=['1', '2', '3', '4', '5'], label='How familiar have you been (1=not at all, 5=very)?', widget=widgets.RadioSelectHorizontal) payoff_crt_bat = models.CurrencyField() payoff_crt_widget = models.CurrencyField() payoff_crt_lake = models.CurrencyField() payoff_crt = models.CurrencyField() def set_crt_payoff(self): if self.crt_bat == 1: self.payoff_crt_bat = 1 else: self.payoff_crt_bat = 0 if self.crt_widget == 5: self.payoff_crt_widget = 1 else: self.payoff_crt_widget = 0 if self.crt_lake == 47: self.payoff_crt_lake = 1 else: self.payoff_crt_lake = 0 self.payoff_crt = 3*(self.payoff_crt_bat + self.payoff_crt_widget + self.payoff_crt_lake) # Survey age = models.IntegerField( label='What is your age?', min=13, max=125) gender = models.StringField( choices=['Male', 'Female', 'Other'], label='What is your gender?', widget=widgets.RadioSelect) country = CountryField( verbose_name='What is your country of citizenship?', blank_label='(select country)') # https://github.com/SmileyChris/django-countries risk = models.StringField( choices=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], label='Assess yourself', widget=widgets.RadioSelectHorizontal) # : Are you more of a risk-taking person or do you think of yourself as a risk-avoider? Please tick a box on the scale below, 0 indicating “no tolerance for risk” and 10 indicating “very risk-seeking”. The values in between can help you more finely represent your image of yourself. # Final payoff def set_payoff(self): self.payoff = self.payoff_dictator_game + self.payoff_public_goods_game + self.payoff_belief + self.payoff_crt # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # class Slider(BaseSlider): # player = ForeignKey(Player)